package xproto

import (
	"reflect"
	"sync"
	"time"
)

// rValue 设备响应数据
type rValue struct {
	Data  interface{}
	Done  chan struct{}
	Error error
}

type rResult struct {
	Vals       sync.Map
	reqTimeout time.Duration
}

// Get 获取
func (r *rResult) GetValue(key interface{}) *rValue {
	if res, ok := r.Vals.Load(key); ok {
		return res.(*rValue)
	}
	return nil
}

// Set 设置
func (r *rResult) SetVal(key string, result interface{}) error {
	if r := r.GetValue(key); r != nil {
		v := reflect.ValueOf(r.Data).Interface().(*interface{})
		*v = result
		r.Done <- struct{}{}
	}
	return nil
}

// SetError 设置错误
func (r *rResult) SetError(key string, err error) error {
	if r := r.GetValue(key); r != nil {
		r.Error = err
		r.Done <- struct{}{}
	}
	return nil
}

// WaitVal 等待结果
func (r *rResult) WaitVal(k string, v interface{}) error {
	if k == "" {
		return ErrParam
	}
	if v == nil || k == "ok" {
		return nil
	}
	val := &rValue{
		Done: make(chan struct{}),
		Data: v,
	}
	r.Vals.Store(k, val)
	defer r.Vals.Delete(k)
	select {
	case <-time.After(time.Second * r.reqTimeout):
		return ErrTimeout
	case <-val.Done:
		return val.Error
	}
}
